#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <time.h>

#define MAXCLIENT 1

int cl_handle(int cl_sock, int bsize){
    /* Recebe o nome do arquivo */
    char* buffer;
    buffer = (char*)malloc(sizeof(char)*bsize);
    char fileName[256];

    int i=0;
    buffer[0] = ' ';  
    while ( buffer[0] != '\0' ){
        if (recv(cl_sock, buffer, 1, 0) < 0){
            perror("recv");
            exit(1);
        }
        fileName[i++] = buffer[0];
    }
    fileName[i] = '\0';

    //abre o arquivo
    FILE *fileIn;
    if( (fileIn = fopen(fileName,"r")) == NULL ){
        close(cl_sock);
        perror("fopen");
        return -1;
    }
    printf("File Open: %s\n", fileName);
    //

    /* Envia o arquivo para o cliente */
    int bytes = 0;
    int sended = 0;
    while ( (bytes = fread(buffer,1,bsize, fileIn)) > 0 ){ 
        if ( send(cl_sock, buffer, bytes,0) < 0){
            perror("send");
            break;
        }
        sended += bytes;
    }

    /* Fecha a conexao com o cliente */
    fclose(fileIn);
    close(cl_sock);
    return sended;
}

int main(int argc, char** argv){
    //tempo inicio
    struct timeval tv;
    double curtime;
    gettimeofday(&tv,NULL);
    curtime= tv.tv_sec + (tv.tv_usec/1000000.0);
    //

    if (argc < 3){
        printf("./servidor porto_servidor tam_buffer\n");
        exit(1);
    }

    //DEFINICAO DA ESTRUTURA DO SERVIDOR

    struct in_addr serv_host;
    serv_host.s_addr = htonl(INADDR_ANY); //inet_addr(argv[1]);
//    serv_host.s_addr = inet_addr("192.168.0.7");

    unsigned short int serv_port;
    serv_port = htons(atoi(argv[1]));

    int buffer_size = atoi(argv[2]);

    int sv_sock, cl_sock;
    struct sockaddr_in sv_addrin, cl_addrin;

    //inicializacao do socket servidor
    if ((sv_sock = socket(AF_INET, SOCK_STREAM, 0)) < 0){
        perror("socket");
        exit(1);
    }
        
    sv_addrin.sin_family = AF_INET;
    sv_addrin.sin_port = serv_port;
    sv_addrin.sin_addr.s_addr = serv_host.s_addr;

    bzero(&(sv_addrin.sin_zero), 8);

    //estabelece abertura passiva 
    if (bind(sv_sock, (struct sockaddr *) &sv_addrin, sizeof(sv_addrin)) < 0){
        perror("bind");
        exit(1);
    }

    if (listen(sv_sock, MAXCLIENT) < 0){

        perror("listen");
        exit(1);
    }
    printf("Aguardando Conexão: %s\n", inet_ntoa(sv_addrin.sin_addr));
    

    //aguarda conexão dos clientes
    int bytes = 0;
    int acpt_size = sizeof(struct sockaddr_in);

    while(bytes >= 0) {
        if ((cl_sock = accept(sv_sock, (struct sockaddr *)&cl_addrin, &acpt_size )) <  0){
            perror("accept");
                exit(1);
        }

        printf("Cliente Conectado: %s\n", inet_ntoa(cl_addrin.sin_addr));

        //abre arquivo e comeca a enviar
        bytes = cl_handle(cl_sock, buffer_size);
        printf("sended: %d bytes\n",bytes);
    }
   // close(cl_sock);
    close(sv_sock);
    exit(0);
}
